#ifndef _MW_SINGLETON_HPP_
#define _MW_SINGLETON_HPP_

#include <cstddef>

namespace mw {
/**
 * \class Singleton
 * A class helps to implement a singleton pattern.
 *
 * You can derive from it:
 *
 * class ClassA: public Singleton<ClassA>
 * {
 *	  ...
 * }
 *
 * ClassA::instance().someMethod();
 *
 * or simply use it like this:
 * 
 * Singleton<ClassA>::instance().someMethod();
 */
template<class Type>
class Singleton
{
public:
	static Type& instance()
	{
		creator_.doNothing();
		static Type instance_;
		return instance_;
	}
private:
	
	/**
	 * \class Singleton::Creator
	 *
	 * Used to make sure the Singleton instance is construct
	 * before main()
	 */
	class Creator
	{
	public:
		Creator()
		{
			Singleton<Type>::instance();
		}
		inline void doNothing() {}
	};
	static Creator creator_;
};

template<class Type>
typename Singleton<Type>::Creator Singleton<Type>::creator_;

/**
 * \class Flexible Singleton
 * 
 * You should create and destroy a Flexible Singleton by youself:
 * first create a derived class like this:
 *
 * class ClassA: public FlexibleSingleton<ClassA>
 * {
 *     ...
 * }
 *
 * then there is two way to manager the lifecycle of the instance:
 *
 * int main()
 * {
 *     ClassA* clsA = new ClassA(...);
 *     ...
 *     delete clsA;
 * }
 *
 * or
 *
 * int main()
 * {
 *     ClassA clsA;
 *     ...
 * }
 *
 */
template<class Type>
class FlexibleSingleton
{
public:
	static Type& instance()
	{
		assert(store() != NULL);
		return (*store());
	}
	FlexibleSingleton()
	{
		assert(store() == NULL);
		store() = this;
	}
	~FlexibleSingleton()
	{
		assert(store() == this);
		store() = NULL;
	}
private:
	static Type*& store()
	{
		static Type* inst = NULL;
		return inst;
	}
};

} // end namespace mw
#endif // _MW_SINGLETON_HPP_
